package com.dean.utils;

import com.dean.constants.DeanUiConstants;
import com.dean.exception.DeanRuntimeException;
import org.apache.poi.util.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.URL;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * @ClassName FileUtis
 * @Description file 工具类
 * @Author dean
 * @Date 2021/11/16 14:55
 */
public class FileUtils {

    private final static Logger logger = LoggerFactory.getLogger(FileUtils.class);

    /**
     * 读取某个目录下的excel文件
     * @param filePath
     * @return
     */
    public static List<File> getExcelFiles(String filePath) {
        List<File> files = new ArrayList<File>();
        File file = new File(filePath);
        if (file.exists() && !file.isDirectory()) {
            return files;
        }
        File [] excelFiles = file.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                if (pathname.getName().endsWith(".xls") || pathname.getName().endsWith(".xlsx")) {
                    if (pathname.getName().startsWith("~$")) {
                        return false;
                    }
                    return true;
                }
                return false;
            }
        });
        files = Arrays.asList(excelFiles);
        return files;
    }


    /**
     * 读取某个目录下的 csv文件
     * @param filePath
     * @return
     */
    public static List<File> getCsvFiles(String filePath) {
        List<File> files = new ArrayList<File>();
        File file = new File(filePath);
        if (file.exists() && !file.isDirectory()) {
            return files;
        }
        File [] excelFiles = file.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                if (pathname.getName().endsWith(".csv") || pathname.getName().endsWith(".csv")) {
                    if (pathname.getName().startsWith("~$")) {
                        return false;
                    }
                    return true;
                }
                return false;
            }
        });
        files = Arrays.asList(excelFiles);
        return files;
    }

    /**
     * 复制资源文件到对应的目录
     */
    public static void copyResourceFile(){
        URL url = FileUtils.class.getProtectionDomain().getCodeSource().getLocation();
        if(url.getPath().endsWith(".jar")){
            copyJarRes(url);
        }else{
            copySysRes(url);
        }
    }

    /**
     * copy jar 中的资源
      */
    public static void  copyJarRes(URL url){
        JarFile jarFile = null;
        try {
            jarFile = new JarFile(url.getFile());
            Enumeration<JarEntry> entrys = jarFile.entries();
            while (entrys.hasMoreElements()) {
                String fileName = entrys.nextElement().getName();
                String [] resPaths = DeanUiConstants.RESOURCE_PATH.split(",");
                for (String resPath : resPaths) {
                    if(fileName.startsWith(resPath)){
                        logger.debug(">>>>>>>>>{}",fileName);
                        copy(fileName);
                        break;
                    }
                }
            }
            jarFile.close();
        } catch (IOException e) {
            logger.error("copy 资源文件失败,失败原因:{}",e.getMessage(),e);
        } finally {
            if (jarFile != null) {
                try {
                    jarFile.close();
                } catch (IOException e) {
                    logger.error("copy 资源文件失败,失败原因:{}",e.getMessage(),e);
                }
            }
        }
    }

    /**
     * 复制系统资源文件
     * @param url
     */
    private static void copySysRes(URL url){
        String [] resPaths = DeanUiConstants.RESOURCE_PATH.split(",");
        for (String resPath : resPaths) {
            copySysRes(resPath,url.getPath()+resPath);
        }
    }

    /**
     * 复制系统资源文件
     * @param resPath
     * @param filePath
     */
    private static void copySysRes(String resPath,String filePath){
        File file = new File(filePath);
        if(file.isDirectory()){
            File [] files = file.listFiles();
            for (File childFile : files) {
                copySysRes(resPath+File.separator+childFile.getName(),childFile.getPath());
            }
        }else{
            copy(resPath);
        }

    }

    /**
     * copy 文件到init目录
     * @param resPath
     */
    private static void copy(String resPath){
        InputStream inputStream = FileUtils.class.getClassLoader().getResourceAsStream(resPath);
        OutputStream outputStream = null;
        try {
            logger.info("初始文件copy:{},{},{}",resPath,File.separator,resPath.substring(0,resPath.lastIndexOf(File.separator)+1));
            File tarFile = new File(DeanUiConstants.INIT_PATH+resPath);
            // 文件存在则不在copy
            if(tarFile.exists()){
                return;
            }
            // 如果是目录 jar 文件
            if(resPath.endsWith("/")){
                tarFile.mkdirs();
                return;
            }
            // 检查系统资源的目录是否存在
            File dir = new File(DeanUiConstants.INIT_PATH+resPath.substring(0,resPath.lastIndexOf(File.separator)+1));
            if(!dir.exists()){
                dir.mkdirs();
            }
            outputStream = new FileOutputStream(DeanUiConstants.INIT_PATH+resPath);
            IOUtils.copy(inputStream,outputStream);
        } catch (FileNotFoundException e) {
            logger.error("copy 资源文件失败,失败原因:{}",e.getMessage(),e);
        } catch (IOException e) {
            logger.error("copy 资源文件失败,失败原因:{}",e.getMessage(),e);
        }
        IOUtils.closeQuietly(inputStream);
        IOUtils.closeQuietly(outputStream);
    }

    /**
     * 批量替换 文件中的内容
     * @param files
     * @param replaceRule
     */
    public void batchReplaceFileContetn(File[] files,Map<String,String> replaceRule){
        for (File file : files) {
            replaceFileContent(file,replaceRule);
        }
    }


    /**
     * 替换文件中的字符按串
     * @param file
     * @param rule 替换规则
     */
    public static void replaceFileContent(File file, Map<String,String> rule){
        // 看看文件有多大
        Long fileLength = file.length();
        byte [] fileContext = new byte[fileLength.intValue()];
        // 将替换后的内容重新写入文件 在当前目录创建新的目录用于存放替换后的文件
        File newDir = new File(file.getParent() + File.separator + "new");
        if(!newDir.exists()){
            newDir.mkdirs();
        }
        String newFileName = newDir+File.separator+file.getName();
        try (FileInputStream fis = new FileInputStream(file);
             FileWriter writer = new FileWriter(newFileName);)
        {
            // 将内容读取到字节流数组中
            fis.read(fileContext);
            // 将字节流数组转为字符串
            String content = new String(fileContext,"utf-8");
            // 根据替换规则替换字符串
            Set<String> keys = rule.keySet();
            for (String key : keys) {
                content = content.replace(key,rule.get(key));
            }
            // 将内容写入文件中
            writer.write(content);
            logger.debug("文件[{}]已完成字符替换,替换后的文件存于[{}]",file.getName(),newFileName);
        } catch (FileNotFoundException e) {
            logger.error(e.getMessage(),e);
        } catch (IOException e) {
            logger.error(e.getMessage(),e);
        }
    }


    /**
     * 将resource 文件copy到本地目录
     * @return
     */
    public static List<String> resourceFileCopy(){
        String preFtlPath = "templates/run/";
        List<String> fileNames = new ArrayList<String>();
        URL url = FileUtils.class.getProtectionDomain().getCodeSource().getLocation();
        String filePath = url.getPath()+preFtlPath;
        JarFile jarFile = null;
        // 如果lei在jar中
        if(url.getPath().endsWith(".jar")){
            try {
                jarFile = new JarFile(url.getFile());
                Enumeration<JarEntry> entrys = jarFile.entries();
                while (entrys.hasMoreElements()  ){
                    String fileName = entrys.nextElement().getName();
                    if(fileName.startsWith(preFtlPath) && fileName.endsWith(".ftl")){
                        // 将文件复制到可用目录
                        String ftlName = fileName.substring(fileName.lastIndexOf("/")+1);
                        fileNames.add(ftlName);
                    }
                }
                jarFile.close();
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                if(jarFile != null){
                    try {
                        jarFile.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }else{
            File ftlPath = new File(filePath);
            File [] files = ftlPath.listFiles(new FileFilter() {
                @Override
                public boolean accept(File pathname) {
                    return pathname.getName().endsWith(".ftl");
                }
            });
            files = files == null?new File[0]:files;
            for (File file : files) {
                fileNames.add(file.getName());
            }
        }
        for (String fileName : fileNames) {
            // 目录不存在则新建目录
            File path = new File(FreemarkerUtils.TEMPLATE_PATH);
            if(!path.exists()){
                path.mkdirs();
            }
            // 将文件复制到目录
            InputStream inputStream = FileUtils.class.getClassLoader().getResourceAsStream("templates/run/"+fileName);
            OutputStream outputStream = null;
            try {
                outputStream = new FileOutputStream(FreemarkerUtils.TEMPLATE_PATH+File.separator+fileName);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
            try {
                IOUtils.copy(inputStream,outputStream);
            } catch (IOException e) {
                e.printStackTrace();
            }
            IOUtils.closeQuietly(inputStream);
            IOUtils.closeQuietly(outputStream);
        }
        return fileNames;
    }

    public static String readFile(String filePath){
        return readFile(filePath,System.getProperty("sun.jnu.encoding"));
    }

    public static String readFile(String filePath,String charset) {
        return readFile(new File(filePath),charset);
    }

    public static String readFile(File file){
        return readFile(file,System.getProperty("sun.jnu.encoding"));
    }

    public static String readFile(File file,String charset) {
       try(FileInputStream fis = new FileInputStream(file)){
           return readFile(fis,charset);
       } catch (IOException e) {
           DeanRuntimeException.throwException(996,e.getMessage(),e);
       }
       return null;
    }

    public static String readFile(FileInputStream fis,String charset) {
        try( InputStreamReader isr = new InputStreamReader(fis,charset); BufferedReader reader = new BufferedReader(isr);){
            StringBuilder sb = new StringBuilder();
            String lineContent = null;
            while((lineContent=reader.readLine())!=null){
                lineContent = lineContent.replaceAll("[\\x00-\\x08-\\x0b-\\x0c-\\x0e-\\x1f]"," ");
                sb.append(lineContent);
                sb.append(System.getProperty("line.separator"));
            }
            return sb.toString();
        }catch (IOException e){
            DeanRuntimeException.throwException(996,e.getMessage(),e);
        }
        return null;
    }
}
